(* 
   Types de la représentation en mémoire du code
*)

type prog = statement list
and statement = Def of decl | DFun of dfun | Expr of expr
and decl = string * expr
and dfun = string * string list * expr
and expr = tree list
and tree = Leaf of lexeme | Node of lexeme * expr list
and lexeme = lex * (int * int)
and lex =
    NUM of Num.num
  | FUN of string
  | VAR of string
  | BOOL of bool
  | UNIT of unit
  | STRING of string

(* Type pour le typeur *)
type type_lex = TNUM | TFUN | TVAR | TBOOL | TUNIT | TSTRING | TPOL of int

(* Fonctions de debuggage *)

let print_lex  = function
  | NUM a -> Num.string_of_num a
  | FUN a -> a
  | VAR a -> a
  | BOOL a -> if a then "true" else "false"
  | UNIT _ -> ""
  | STRING a -> a

let d_print_lex  = function
  | NUM a -> "Num = "^Num.string_of_num a
  | FUN a -> "Fun =  "^a
  | VAR a -> "Var = "^a
  | BOOL a -> "Bool = "^(if a then "true" else "false")
  | UNIT _ -> "Unit = ()"
  | STRING a -> "String = \""^a^"\""

let print_tlex  = function
  | TNUM -> "Num"
  | TFUN -> "Fun"
  | TVAR -> "Var"
  | TBOOL -> "Bool"
  | TUNIT -> "Unit"
  | TSTRING -> "String"
  | TPOL a -> "'"^(String.make 1 (char_of_int (a+97)))



let print_tree l =
  let indent n s =
    for x = 1 to n do print_string (s^"    ") done in
  let rec aux tree n = match tree with
    | Leaf (a, e) -> indent n "|" ; print_string (d_print_lex a); print_newline ()
    | Node((r, c), cl) ->
	indent n "|"; print_endline (d_print_lex r);
	List.iter (fun l -> print_endline "["; print_expr l (n+1); print_endline "]") cl
  and print_expr l n = 
    List.iter (fun x -> aux x n) l
  in print_expr l 0
